#include "CSkillMgr.h"
#include <iostream>
#include <fstream>
#include "pb_cfg_skill.pb.h"

#include "../mainctrl.h"
#include "commmsg.h"
#include "commerrno.h"

int CSkillMgr::LoadConfig(const char* szCfgPath)
{
    int iRet = 0;
    int iIndex = 0;

    if (szCfgPath == NULL)
    {
        CT_ERROR(("Skill Cfg Path is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_skill stSkillCfg;
    std::fstream stFileInput(szCfgPath, std::ios::in | std::ios::binary);
    if (!stSkillCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse SkillCfg!"));
        return RET_SYSTEM_FAIL;
    }

    //解析配置文件内容
    CT_TRACE(("begin skill effect cfg(%d)",stSkillCfg.skilleffect_cfg_rows_size()));

    //技能效果
    
    CSkillEffect stSkillEffect;
    for (int i = 0; i < stSkillCfg.skilleffect_cfg_rows_size(); ++i)
    {
        const pb_cfg_skill_pb_cfg_skilleffect_cfg_unit& stEffUnit 
            = stSkillCfg.skilleffect_cfg_rows(i);

        stSkillEffect.Clear();

        stSkillEffect.SetStatType((unsigned char)stEffUnit.stat_type());
        stSkillEffect.SetSubType((unsigned char)stEffUnit.sub_type());
        stSkillEffect.SetID((unsigned int)stEffUnit.id());
        stSkillEffect.SetTriggerRate(stEffUnit.trigger_rate());
        stSkillEffect.SetType(stEffUnit.data_type());
        stSkillEffect.SetData(stEffUnit.data());
        stSkillEffect.SetLast(stEffUnit.turn_last());
        stSkillEffect.SetAuxData(stEffUnit.aux_data());

        iRet = _stSkillEffCfg.AddConfig(stSkillEffect);
        CT_RETURN(iRet);
    }

    //技能功能
    CT_TRACE(("begin skill affect cfg(%d)",stSkillCfg.skillaffect_cfg_rows_size()));

    CSkillAffect stSkillAffect;
    CTLib::CTArray<unsigned int, MAX_EFFECT_PER_SKILL> auiSkillEffectID;

    for (int i = 0; i < stSkillCfg.skillaffect_cfg_rows_size(); ++i)
    {
        const pb_cfg_skill_pb_cfg_skillaffect_cfg_unit& stAffUnit 
            = stSkillCfg.skillaffect_cfg_rows(i);

        stSkillAffect.Clear();

        stSkillAffect.SetValid((stAffUnit.is_valid() == 0 ? false : true));
        stSkillAffect.SetToEnemy((stAffUnit.is_to_enemy() == 0 ? false : true));
        stSkillAffect.SetPhy((stAffUnit.is_phy() == 0 ? false : true));
        stSkillAffect.SetTargetType((unsigned char)stAffUnit.target_type());
        stSkillAffect.SetTargetStru((unsigned char)stAffUnit.target_stru());
        stSkillAffect.SetID((unsigned int)stAffUnit.id());
        stSkillAffect.SetMaxAtkDistance(stAffUnit.atk_distance());
        stSkillAffect.SetRecommendDistance(stAffUnit.recommend_distance());
        stSkillAffect.SetEffectRange(stAffUnit.effect_range());
        stSkillAffect.SetAtkValue(stAffUnit.atk_value());

        auiSkillEffectID.Clear();
        auiSkillEffectID.AddOneItem((unsigned int)stAffUnit.effect_id_1());
        auiSkillEffectID.AddOneItem((unsigned int)stAffUnit.effect_id_2());
        auiSkillEffectID.AddOneItem((unsigned int)stAffUnit.effect_id_3());
        auiSkillEffectID.AddOneItem((unsigned int)stAffUnit.effect_id_4());
        auiSkillEffectID.AddOneItem((unsigned int)stAffUnit.effect_id_5());

        for (int i = 0; i < auiSkillEffectID.Size(); ++i)
        {
            if (auiSkillEffectID[i] <= 0)
            {
                continue;
            }

            iIndex = _stSkillEffCfg.FindConfig(auiSkillEffectID[i]);
            if (iIndex >= 0)
            {
                stSkillAffect.AddSkillEffect(_stSkillEffCfg.GetConfig(iIndex));
            }
            else
            {
                CT_ERROR(("skill effect(%u) empty at skill affect cfg(%u)",
                          auiSkillEffectID[i], stSkillAffect.GetID()));
                CT_RETURN(ERROR_SKILL_EFF_EMPTY_CFG);
            }
        }

        iRet = _stSkillAffCfg.AddConfig(stSkillAffect);
        if (iRet)
        {
            CT_ERROR(("skill affect(%u) error(%d)",stSkillAffect.GetID(),iRet));
            return iRet;
        }
        
        CT_RETURN(iRet);
    }

    //技能
    CT_TRACE(("begin skill cfg(%d)",stSkillCfg.skill_cfg_rows_size()));

    CSkill stSkill;
    unsigned int uiSkillAffectID = 0;
    for (int i = 0; i < stSkillCfg.skill_cfg_rows_size(); ++i)
    {
        const pb_cfg_skill_pb_cfg_skill_cfg_unit& stSkillUnit 
            = stSkillCfg.skill_cfg_rows(i);

        stSkill.Clear();

        stSkill.SetType(stSkillUnit.skill_type());
        stSkill.SetID((unsigned int)stSkillUnit.id());
        stSkill.SetUseAnger(stSkillUnit.use_anger());
        stSkill.SetUseHPPercent(stSkillUnit.use_hp());
        stSkill.SetNoAttack(stSkillUnit.no_attack());
        stSkill.SetTargetType(stSkillUnit.skill_target_type());

        if (!stSkill.IsValidType())
        {
            CT_ERROR(("skill(%u) type(%d) error",
                      stSkill.GetID(),stSkill.GetType()));
            CT_RETURN(ERROR_SKILL_ERROR_CFG);
        }

        uiSkillAffectID = (unsigned int)stSkillUnit.main_aff_id();
        if (uiSkillAffectID > 0)
        {
            iIndex = _stSkillAffCfg.FindConfig(uiSkillAffectID);
            if (iIndex >= 0)
            {
                stSkill.SetMainAffect(_stSkillAffCfg.GetConfig(iIndex));
            }
            else
            {
                CT_ERROR(("skill affect(%u) empty at skill cfg(%u)",
                          uiSkillAffectID, stSkill.GetID()));
                CT_RETURN(ERROR_SKILL_AFF_EMPTY_CFG);
            }
        }

        uiSkillAffectID = (unsigned int)stSkillUnit.minor_aff_id();
        if (uiSkillAffectID > 0)
        {
            iIndex = _stSkillAffCfg.FindConfig(uiSkillAffectID);
            if (iIndex >= 0)
            {
                stSkill.SetMinorAffect(_stSkillAffCfg.GetConfig(iIndex));
            }
            else
            {
                CT_ERROR(("skill affect(%u) empty at skill cfg(%u)",
                          uiSkillAffectID, stSkill.GetID()));
                CT_RETURN(ERROR_SKILL_AFF_EMPTY_CFG);
            }
        }

        iRet = _stSkillCfg.AddConfig(stSkill);
        if (iRet)
        {
            CT_ERROR(("skill(%u) error(%d)", stSkill.GetID(), iRet));
        }
        CT_RETURN(iRet);
    }

    return 0;
}

//技能存在性、类别的简单检查
int CSkillMgr::IsValidSkill(unsigned int uiSkillID, int iSkillType)
{
    if (uiSkillID == 0)
    {
        return 0;
    }

    int iIndex = 0;
    iIndex = FindSkillCfg(uiSkillID);
    if (iIndex < 0)
    {
        CT_ERROR(("skill(%u) not exist",uiSkillID));
        CT_RETURN(ERROR_SKILL_EMPTY_CFG);
    }

    CSkill& stSkill = GetSkillCfg(iIndex);

    if (stSkill.GetType() != iSkillType)
    {
        CT_ERROR(("skill(%u) type(%d) not given type(%d)",
                  uiSkillID,stSkill.GetType(),iSkillType));
        CT_RETURN(ERROR_SKILL_ERROR_CFG);
    }

    return 0;
}

int CSkillMgr::GetSkillByID(CSkill& stSkill, unsigned int uiSkillID, int iType)
{
    int iIndex = 0;
    iIndex = FindSkillCfg(uiSkillID);
    CT_CHECK(iIndex, ERROR_SKILL_EMPTY_CFG);

    CSkill& stSkillCfg = GetSkillCfg(iIndex);

    if (!stSkillCfg.IsValidType(iType))
    {
        CT_WARNING(("given skill type(%d) error",iType));
        return ERROR_SKILL_ERROR_CFG;
    }

    if (stSkillCfg.GetType() != iType)
    {
        CT_WARNING(("skill(%u) type(%d) not given type(%d)",
                    uiSkillID,stSkillCfg.GetType(),iType));
        return ERROR_SKILL_ERROR_CFG;
    }

    stSkill = stSkillCfg;

    return 0;
}
